package com.lin.filegraph.service.impl;

import com.lin.filegraph.exception.FileGraphErrorException;
import com.lin.filegraph.service.IStartFileGraph;
import com.lin.filegraph.utils.extractor.JavaInfoExtractor;
import com.lin.filegraph.utils.filedg.FileGraph;
import com.lin.filegraph.utils.filedg.FileGraphEdge;
import com.lin.filegraph.utils.filedg.FileGraphNode;
import com.lin.filegraph.utils.moduledg.ModuleInfo;
import com.lin.filegraph.utils.parser.node.JProjectNode;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Service
public class StartFileGraphImpl implements IStartFileGraph {

    //生成文件依赖图
    public FileGraph createFileGraph(String projectPath, JProjectNode root, String depend, int loc, boolean filterTest, List<ModuleInfo> moduleInfoList) throws FileGraphErrorException {
        System.out.println("从AST中抽取各个文件之间的依赖关系");
        FileGraph fileGraph = JavaInfoExtractor.getFileGraph(projectPath, root, loc, depend, filterTest);

        if (moduleInfoList != null) {
            fixFileGraph(fileGraph, moduleInfoList);
        }
        //文件依赖图生成完毕
        System.out.println("文件依赖图生成模块结束");
        return fileGraph;
    }

    //对文件图进行修正，解决多模块情况下同名同包导致的文件匹配错误情况
    public FileGraph fixFileGraph(FileGraph fileGraph, List<ModuleInfo> moduleInfoList) {
        List<FileGraphEdge> fileGraphEdgeList = fileGraph.getListOfFileEdges();
        List<FileGraphNode> fileGraphNodeList = fileGraph.getFileGraphNode();
        for (FileGraphEdge edge : fileGraphEdgeList) {
            FileGraphNode preFileNode = edge.getPreFile();
            FileGraphNode postFileNode = edge.getPostFile();
            //在preFileNode所在模块内，查找是否有同包同名的文件
            FileGraphNode sameFile = findSameFile(moduleInfoList, fileGraphNodeList, preFileNode, postFileNode);
            if (sameFile != null) {
                edge.setPostFile(sameFile);
            }
        }
        return fileGraph;
    }

    public FileGraphNode findSameFile(List<ModuleInfo> moduleInfoList, List<FileGraphNode> fileGraphNodeList, FileGraphNode preFileNode, FileGraphNode postFileNode) {
        //查找preFile所在模块
        ModuleInfo preModule = null;
        for (ModuleInfo moduleInfo : moduleInfoList) {
            if (preFileNode.getAbsolutePath().contains(moduleInfo.getModulePath())) {
                preModule = moduleInfo;
            }
        }
        //查找preFile所在模块中，是否存在与postFile同名同包的文件
        for (FileGraphNode fileGraphNode : fileGraphNodeList) {
            //如果当前文件与pre同模块&&与post文件同包名&&与post文件同名&&不是post文件
            String[] postNameList = postFileNode.getFileName().split("\\\\");
            String[] curNameList = fileGraphNode.getFileName().split("\\\\");
            if (preModule != null && fileGraphNode.getAbsolutePath().contains(preModule.getModulePath()) && fileGraphNode.getPackageName().equals(postFileNode.getPackageName()) && postNameList[postNameList.length - 1].equals(curNameList[curNameList.length - 1]) && !fileGraphNode.getAbsolutePath().equals(postFileNode.getAbsolutePath())) {
                return fileGraphNode;
            }
        }
        return null;
    }

    public static String changeFileName(String s) {
        String[] str = s.split("/");
        return str[str.length - 1];
    }

    public String getDateAndMessage(String str) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String newStr = sdf.format(date) + str;
        return newStr;
    }

//    //根据文件获取所在模块
//    public static ModuleNode getModuleByFileGraphNode(FileGraphNode fileGraphNode, List<ModuleNode> listOfModules) {
//        for (ModuleNode Module : listOfModules) {
//            if (isContains(Module.getAllFiles(), fileGraphNode)) {
//                return Module;
//            }
//        }
//        return null;
//    }

    public static boolean isContains(List<FileGraphNode> listOfFiles, FileGraphNode fileGraphNode) {
        for (FileGraphNode node : listOfFiles) {
            if (node.getAbsolutePath().equals(fileGraphNode.getAbsolutePath())) {
                return true;
            }
        }
        return false;
    }
}
